
#include "usart.h"
#include "main.h"
#include "config.h"
#include "nb.h"
#include "gpio.h"

#define NBRXFLAG     NB_UART_RX.flag
#define NBRXBUFF     NB_UART_RX.buff
#define NBRXLEN      NB_UART_RX.len
#define NBSEND(a, b) usart_send_data(&NB_UART, a, b)

#define NB_BUFF_SIZE        UART2_BUFF_SIZE
#define NBHexStrTxBuffer    NBRXBUFF
#define NBHexStrTxBufferLen NBRXLEN

#define INT_MAX ((int)0x7FFFFFFF)
#define INT_MIN ((int)0x80000000)

static uint8_t socketid = 0;
uint8_t        imei[15] = { 0 };

nb_status_e nbled = NB_IDLE;
static void nb_reset(void)
{
    msg_printf("nb hard reset\r\n");
    nbrst_on();
    HAL_Delay(200);
    nbrst_off();
}

extern uint8_t  tcp_rx_buff[255];
extern uint16_t tcp_rx_size;

static int32_t myatoi(const char* str, const int len)
{
    int       minus = 0;
    long long result = 0;
    int       rst = 0;

    if (str == NULL)
        return 0;
    while (*str == ' ')
        str++;
    if (*str == '-') {
        minus = 1;
        str++;
    } else if (*str == '+')
        str++;
    if (*str < '0' || *str > '9')
        return 0;

    while ((*str >= '0' && *str <= '9') && (rst < len)) {
        result = result * 10 + *str - '0';
        if ((minus && result > INT_MAX + 1LL) || (!minus && result > INT_MAX)) {
            return 0;
        }

        str++;
        rst++;
    }

    if (minus)
        result *= -1;
    return (int)result;
}

static uint8_t nb_check_power_on(void)
{
    uint8_t len = 0, retry = 0;
    char    buff[128];

    msg_printf("nb check init ");
		nbled = NB_CHECK_AT;
    retry = 50;
    while (retry--) {

        usart_rx_buff_clear(&NB_UART_RX);

        len = sprintf((char*)buff, "AT\r\n");
        NBSEND((uint8_t*)buff, len);

        HAL_Delay(200);

        if (NBRXFLAG) {
            NBRXFLAG = 0;
            if (('O' == NBRXBUFF[2]) && ('K' == NBRXBUFF[3])) {
                msg_printf("done\r\n");
                return 1;
            }
        }
    }
    msg_printf("error\r\n");
    return 0;
}

uint8_t nb_tcp_soft_reboot(void)
{
    uint32_t len = 0, i = 50;
    char     buff[128];

    msg_printf("nb soft reboot \r\n");

    while (i--) {

        usart_rx_buff_clear(&NB_UART_RX);

        len = sprintf((char*)buff, "AT+NRB\r\n");
        NBSEND((uint8_t*)buff, len);
        msg_printf("%s", buff);
        HAL_Delay(200);

        if (NBRXFLAG) {
            NBRXFLAG = 0;
            msg_printf("%s", NBRXBUFF);
            if (strstr((char*)NBRXBUFF, (char*)"OK")) {
                msg_printf("done\r\n");
                return 1;
            }
        }
        msg_printf(".");
    }
    msg_printf("error\r\n");
    return 0;
}

static uint8_t nb_tcp_connect(uint8_t ip1, uint8_t ip2, uint8_t ip3, uint8_t ip4, uint32_t port)
{
    uint32_t len = 0, retry = 0;
    char     buff[128];

    msg_printf("nb tcp creat socket");
		nbled = NB_TRY_CONNECT;
    usart_rx_buff_clear(&NB_UART_RX);
    len = sprintf((char*)buff, "AT+NSOCR=\"STREAM\",6,60003,1\r\n");
    NBSEND((uint8_t*)buff, len);
    //msg_printf("%s", buff);

    retry = 0;
    while (!NBRXFLAG && retry < 10) {
        retry++;
        HAL_Delay(200);
    }

    if (NBRXFLAG) {
        NBRXFLAG = 0;
        //msg_printf("%s", NBRXBUFF);
        if (!strstr((char*)NBRXBUFF, (char*)"OK")) {
            msg_printf("error\r\n");
            return 0;
        } else {
            socketid = (uint8_t)NBRXBUFF[2] - '0';
            msg_printf("done\r\n");
        }
    } else {
				msg_printf("error no rx flag\r\n");
        return 0;
    }

    HAL_Delay(500);

    usart_rx_buff_clear(&NB_UART_RX);
    len = sprintf((char*)buff, "AT+NSOCO=%d,%d.%d.%d.%d,%d\r\n", socketid, ip1, ip2, ip3, ip4, port);
    NBSEND((uint8_t*)buff, len); //Socket connect to ip port
    //msg_printf("%s", buff);

    msg_printf("nb tcp socket connect to %d.%d.%d.%d,%d\r\n", ip1, ip2, ip3, ip4, port);

    retry = 0;
    while (retry < 1000) {
        if (NBRXFLAG) {
            NBRXFLAG = 0;
            //msg_printf("%s", NBRXBUFF);
            if (strstr((char*)NBRXBUFF, (char*)"CONNECT OK")) {
                msg_printf("done\r\n");
								nbled = NB_CONNECTED;
                HAL_Delay(1000);
                return 1;
            }
        }
        retry++;
        HAL_Delay(10);
    }

    msg_printf("error\r\n");
    return 0;
}

uint8_t nb_tcp_disconnect(void)
{
    uint16_t len = 0, retry = 0;
    char     buff[128];

    msg_printf("nc tcp socket disconnected ");

    usart_rx_buff_clear(&NB_UART_RX);
    len = sprintf((char*)buff, "AT+NSOCL=%d\r\n", socketid);
    NBSEND((uint8_t*)buff, len);
    //msg_printf("%s", buff);

    retry = 0;
    while (!NBRXFLAG && retry < 10) {
        retry++;
        HAL_Delay(200);
    }

    if (NBRXFLAG) {
        NBRXFLAG = 0;
        //msg_printf("%s", NBRXBUFF);
        if (strstr((char*)NBRXBUFF, (char*)"OK")) {
            msg_printf("done\r\n");
						nbled = NB_DISCONNECTED;
            HAL_Delay(5000);
						nbled = NB_IDLE;
            return 1;
        }
    }

    msg_printf("error");
    return 0;
}

static uint8_t nb_attach_net(void)
{
    uint32_t len = 0, retry = 0, i = 0;
    char     buff[128];

    msg_printf("nb tcp attach net ");
		nbled = NB_ATTACH_NET;
    i = 200;
    while (i--) {

        usart_rx_buff_clear(&NB_UART_RX);
        len = sprintf((char*)buff, "AT+CGATT?\r\n");
        NBSEND((uint8_t*)buff, len);

        retry = 0;
        while (!NBRXFLAG && retry < 10) {
            HAL_Delay(200);
            retry++;
        }
        if (NBRXFLAG) {
            NBRXFLAG = 0;
            if (strstr((char*)NBRXBUFF, (char*)"+CGATT:1")) {
                msg_printf("done\r\n");
                return 1;
            }
        }

        if (DEBUG_UART_RX.flag && DEBUG_UART_RX.len > 2) {
            msg_printf("\r\nexit\r\n");
            return 0;
        }
    }

    if (i == 0) {
        msg_printf("error\r\n");
        return 0;
    }

    return 0;
}

uint8_t nt_tcp_get_module_imei(char* ptr)
{
    uint32_t len = 0, i = 10;
    char*    pchar;
    char     buff[128];

    msg_printf("nb get module imei: ");

    while (i--) {

        usart_rx_buff_clear(&NB_UART_RX);
        len = sprintf((char*)buff, "AT+CGSN=1\r\n");
        NBSEND((uint8_t*)buff, len);
        //msg_printf("%s", buff);

        HAL_Delay(200);

        if (NBRXFLAG) {
            NBRXFLAG = 0;
            pchar = strstr((char*)NBRXBUFF, (char*)"+CGSN:");
            if (pchar) {
                pchar = strtok((char*)NBRXBUFF, ":");
                pchar = strtok(NULL, ":");
                sscanf(pchar, "%15s", ptr);
                msg_printf("%s\r\n", ptr);
                return 1;
            }
        }
    }
    msg_printf("error\r\n");
    return 0;
}

uint8_t nb_tcp_module_init(uint8_t ip1, uint8_t ip2, uint8_t ip3, uint8_t ip4, uint32_t port)
{
    uint32_t len = 0, retry = 0, i = 0;
    retry = 0;

RETRY:

    nb_reset();

    //if (!nb_tcp_reboot()) {
    //    return 0;
    //}

    if (!nb_check_power_on()) {
        return 0;
    }

    if (!nt_tcp_get_module_imei(imei)) {
        return 0;
    }

    if (!nb_attach_net()) {
        return 0;
    }

    msg_printf("imei %s\r\n", imei);

    HAL_Delay(100);

    while (!nb_tcp_connect(ip1, ip2, ip3, ip4, port)) {
        msg_printf("retry,%d\r\n", retry);
        retry++;
        HAL_Delay(500);
        if (retry < 3) {
            goto RETRY;
        } else {
            msg_printf("nb tcp module init error\r\n");
            return 0;
        }
    }

    msg_printf("nb tcp module init done\r\n");
    return 1;
}

uint8_t nb_tcp_send(uint8_t* pHexdata, uint16_t datalen)
{
    uint32_t i = 0, len = 0, retry = 0;
    char     buff[512];

    usart_rx_buff_clear(&NB_UART_RX);
    len = sprintf(buff, "AT+NSOSD=%d,%d,", socketid, datalen);
    for (i = 0; i < datalen; i++) {
        sprintf((char*)(buff + len + 2 * i), "%x%x", *(pHexdata + i) >> 4, *(pHexdata + i) & 0x0f);
    }
    len += (datalen << 1);
    buff[len++] = 0x0d;
    buff[len++] = 0x0a;

    msg_printf("nb tcp payload:");
    for (i = 0; i < len; i++) {
        msg_printf("%.2x ", buff[i]);
    }
    msg_printf("\r\n");

    NBSEND((uint8_t*)buff, len);
    msg_printf("%s", buff);

    retry = 0;
    while ((!NBRXFLAG) && (retry < 200)) {
        retry++;
        HAL_Delay(10);
    }

    if (NBRXFLAG) {
        NBRXFLAG = 0;
        msg_printf("%s", NBRXBUFF);
        if (strstr((char*)NBRXBUFF, (char*)"OK")) {
            msg_printf("send done\r\n");
            HAL_Delay(2000);
            return 1;
        }
    } else {
        msg_printf("send error\r\n");
        HAL_Delay(2000);
        return 0;
    }
    HAL_Delay(2000);
    return 0;
}

uint8_t nb_tcp_get_module_buff_data(void)
{
    uint32_t dt = 0, i = 0;
    uint16_t len = 0;
    char*    pchar;
    uint8_t  temp8 = 0;
    char     buff[128];

    usart_rx_buff_clear(&NB_UART_RX);
    len = sprintf(buff, "AT+NSORF=%d,255\r\n", socketid);
    NBSEND((uint8_t*)buff, len);
    msg_printf("%s", buff);

    while (!NBRXFLAG && dt < 100) {
        HAL_Delay(10);
        dt++;
    }
    if (NBRXLEN < NB_BUFF_SIZE) {
        NBRXBUFF[NBRXLEN] = 0;
    } else {
        return 0;
    }

    if (NBRXFLAG) {
        NBRXFLAG = 0;
        pchar = strstr((char*)NBRXBUFF, (char*)"+NSORF:");
        if (pchar != 0) {
            pchar = strtok((char*)NBRXBUFF, ",");
            i = 0;
            dt = 0;
            while (pchar != 0) {
                if (i == 3) {
                    tcp_rx_size = (uint16_t)myatoi((char*)pchar, 5);
                    len = tcp_rx_size;
                    msg_printf("tcp_rx_size:%d\r\n", tcp_rx_size);
                }
                if (i == 4) {
                    for (i = 0; i < len; i++) {
                        if (pchar[0] >= '0' && pchar[0] <= '9') {
                            temp8 = (pchar[0] - '0') << 4;
                        } else if (pchar[0] >= 'A' && pchar[0] <= 'F') {
                            temp8 = (pchar[0] - 'A' + 10) << 4;
                        } else if (pchar[0] >= 'a' && pchar[0] <= 'f') {
                            temp8 = (pchar[0] - 'a' + 10) << 4;
                        } else {
                            break;
                        }

                        if (pchar[1] >= '0' && pchar[1] <= '9') {
                            temp8 |= (pchar[1] - '0');
                        } else if (pchar[1] >= 'A' && pchar[1] <= 'F') {
                            temp8 |= (pchar[1] - 'A' + 10);
                        } else if (pchar[1] >= 'a' && pchar[1] <= 'f') {
                            temp8 |= (pchar[1] - 'a' + 10);
                        } else {
                            break;
                        }
                        tcp_rx_buff[i] = temp8;
                        pchar += 2;
                    }
                    if (i == len) {
                        msg_printf("tcp_rx_buff:");
                        msg_printf_hex(tcp_rx_buff, tcp_rx_size);
                        return 1;
                    }
                }
                i++;
                pchar = strtok(0, ",");
            }
        }
    }
    return 0;
}
